
#pragma once

#include "GLmath.h"
#include "GLvec3.h"

class GLbbox
{
public:
	GLvec3f min,max;
public:
	GLbbox(){
		SetEmpty();
	}

	void SetEmpty()
	{
		min = GLvec3f( FLT_MAX,FLT_MAX,FLT_MAX);
		max = GLvec3f( -FLT_MAX,-FLT_MAX,-FLT_MAX); 
	};
	
	bool IsEmpty()const 
	{ 
		if(max.x>=min.x)
			return false;
		if(max.y>=min.y)
			return false;
		if(max.z>=min.z)
			return false;
		return true;
	}

	void AddVertex( const GLvec3f& vec )
	{
		if(vec.x<min.x)min.x = vec.x;
		if(vec.y<min.y)min.y = vec.y;
		if(vec.z<min.z)min.z = vec.z;

		if(vec.x>max.x)max.x = vec.x;
		if(vec.y>max.y)max.y = vec.y;
		if(vec.z>max.z)max.z = vec.z;
	}
	
	GLbbox operator+( const GLbbox& b )const 
	{ 
		GLbbox box;
		box = b;
		box.Merge(*this);
		return box;
	}
	GLbbox& operator=(const GLbbox& rhs)
	{ 
		min = rhs.min;
		max = rhs.max;
		return *this;
	}
	
	void Merge( const GLbbox& box )
	{
		assert( !box.IsEmpty());

		if( IsEmpty() )
		{
			min = box.min;
			max = box.max;
		}
		else
		{
			if( box.min.x < min.x ) min.x = box.min.x;
			if( box.min.y < min.y ) min.y = box.min.y;
			if( box.min.z < min.z ) min.z = box.min.z;

			if( box.max.x > max.x ) max.x = box.max.x;
			if( box.max.y > max.y ) max.y = box.max.y;
			if( box.max.z > max.z ) max.z = box.max.z;
		}

		assert( !IsEmpty());
		assert( Contain( box ));
	}
	
	bool Contain( const GLbbox& box )
	{
		if( box.min.x < min.x ) return false;
		if( box.min.y < min.y ) return false;
		if( box.min.z < min.z ) return false;

		if( box.max.x > max.x ) return false;
		if( box.max.y > max.y ) return false;
		if( box.max.z > max.z ) return false;

		return true;
	}

	GLvec3f Center(){return (min+max)/2.f;}
	
	bool IsPointInside( const GLvec3f& v,float epsilon = ON_EPSILON )
	{
		for( int i = 0;i<3;i++ )
		{
			float d = v[i] - min[i];
			if( d <= -epsilon)
				return false;
		}

		for( int i = 0;i<3;i++ )
		{
			float d = v[i] - max[i];
			if( d  >= epsilon )
				return false;
		}

		return true;
	}

	void GetVerts( GLvec3f* verts) const
	{
		verts[0] = verts[1] = verts[2] = verts[3] = min;
		verts[4] = verts[5] = verts[6] = verts[7] = max;

		verts[1].x = max.x;
		verts[3].y = max.y;

		verts[2].x = max.x;
		verts[2].y = max.y;

		verts[5].y = min.y;
		verts[7].x = min.x;

		verts[4].x = min.x;
		verts[4].y = min.y;
	}

	void GetTriVerts( GLvec3f* triVerts ) const
	{
		GLvec3f verts[8];
		
		GetVerts( verts );

		int index[12*3] = {0,1,2,0,2,3,1,5,6,1,6,2,5,4,7,5,7,6,4,0,3,4,3,7,3,2,6,3,6,7,1,0,4,1,4,5};

		for( int i = 0;i<36;i++)
		{
			triVerts[i] = verts[index[i]];
		}
	}
};